package com.tegtech.common.utils.date;

import java.lang.management.ManagementFactory;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.FastDateFormat;

import cn.hutool.core.util.StrUtil;

/**
 * 日期工具类
 * 
 * @Author Jun
 * @date 2020年7月6日 下午5:39:13
 */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {

	/**
	 * 日期解析匹配器
	 */
	private static String[] parsePatterns = { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH",
			"yyyy-MM", "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM/dd HH", "yyyy/MM",
			"yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM.dd HH", "yyyy.MM", "yyyy年MM月dd日",
			"yyyy年MM月dd日 HH时mm分ss秒", "yyyy年MM月dd日 HH时mm分", "yyyy年MM月dd日 HH时", "yyyy年MM月", "yyyy" };

	/**
	 * 获取当前Date型日期
	 * 
	 * @return Date 当前日期
	 */
	public static Date now() {
		return new Date();
	}

	/**
	 * 将毫秒值转为Date型日期
	 * 
	 * @param millis 毫秒数
	 * @return Date 当前日期
	 */
	public static Date date(long millis) {
		return new Date(millis);
	}
	
	/**
	 * 将日期转换为毫秒值
	 * @param date
	 * @return
	 */
	public static long millis(Date date) {
		return date == null ? 0 : date.getTime();
	}
	
	/**
	 * 将日期转换为毫秒值
	 * @param date
	 * @return
	 */
	public static long millis(String dateStr) {
		Date date = null;
		try {
			date = parseDate(dateStr, DatePattern.YYYY_MM_DD_HH_MM_SS);
		} catch (ParseException e) {
			return 0;
		}
		return millis(date);
	}

	/**
	 * 获取当前unix时间戳，单位：秒
	 * @return
	 */
	public static long unix() {
		return System.currentTimeMillis() / 1000L;
	}
	
	/**
	 * 得到日期时间字符串，转换格式（yyyy-MM-dd HH:mm:ss）
	 */
	public static String formatDateTime(Date date) {
		return formatDate(date, DatePattern.YYYY_MM_DD_HH_MM_SS);
	}
	
    /**
     * 得到当前日期字符串 格式（yyyy-MM-dd） pattern可以为："yyyy-MM-dd" "HH:mm:ss" "E"
     */
    public static String formatCurrentDate(String pattern) {
        return formatDate(now(), pattern);
    }
	
	/**
	 * 得到日期字符串 默认格式（yyyy-MM-dd） pattern可以为："yyyy-MM-dd" "HH:mm:ss" "E"
	 */
	public static String formatDate(long millis, String pattern) {
		return formatDate(date(millis), pattern);
	}

	/**
	 * 得到日期字符串 默认格式（yyyy-MM-dd） pattern可以为："yyyy-MM-dd" "HH:mm:ss" "E"
	 */
	public static String formatDate(Date date, String pattern) {
		String formatDate = null;
		if (date != null) {
			if (StrUtil.isBlank(pattern)) {
				pattern = DatePattern.YYYY_MM_DD;
			}
			formatDate = FastDateFormat.getInstance(pattern).format(date);
		}
		return formatDate;
	}

	/**
	 * 获取未来某天的日期
	 *
	 * @param past
	 * @return
	 */
	public static Date getFetureDate(Date date, int n) {
		Calendar curr = Calendar.getInstance();
		curr.setTime(date);
		curr.add(Calendar.DAY_OF_MONTH, n);
		return curr.getTime();
	}

	/**
	 * 获取未来某天的日期的开始时间
	 *
	 * @param past
	 * @return
	 */
	public static Date getFetureStartDate(Date date, int n) {
		Calendar curr = Calendar.getInstance();
		curr.setTime(date);
		curr.add(Calendar.DAY_OF_MONTH, n);
		curr.set(Calendar.HOUR_OF_DAY, 0);
		curr.set(Calendar.MINUTE, 0);
		curr.set(Calendar.SECOND, 0);
		curr.set(Calendar.MILLISECOND, 0);
		return curr.getTime();
	}
	
	/**
	 * 得到当前日期前后多少天，月，年的日期字符串
	 *
	 * @param pattern 格式（yyyy-MM-dd） pattern可以为："yyyy-MM-dd" "HH:mm:ss" "E"
	 * @param type    类型，可参考Calendar的常量(如：Calendar.HOUR、Calendar.MINUTE、Calendar.SECOND)
	 * @param amont   数量，前为负数，后为正数
	 * @return
	 */
	public static String getDate(String pattern, int type, int amont) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(now());
		calendar.add(type, amont);
		return FastDateFormat.getInstance(pattern).format(calendar.getTime());
	}

	/**
	 * 得到当前日期前后多少天，月，年的日期毫秒值
	 *
	 * @param amont 数量，前为负数，后为正数
	 * @param type  类型，可参考Calendar的常量(如：Calendar.HOUR、Calendar.MINUTE、Calendar.SECOND)
	 * @return
	 */
	public static Long getDate(int type, int amont) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(now());
		calendar.add(type, amont);
		return calendar.getTime().getTime();
	}

	/**
	 * 日期型字符串转化为日期 格式 see to DateUtils#parsePatterns
	 */
	public static Date parseDate(Object str) {
		if (str == null) {
			return null;
		}
		try {
			return parseDate(str.toString(), parsePatterns);
		} catch (ParseException e) {
			return null;
		}
	}

	/**
	 * 获取服务器启动时间
	 */
	public static Date getServerStartDate() {
		long time = ManagementFactory.getRuntimeMXBean().getStartTime();
		return date(time);
	}

	/**
	 * 计算两个时间差
	 */
	public static String getDatePoor(Date biginDate, Date endDate) {
		long nd = 1000 * 24 * 60 * 60;
		long nh = 1000 * 60 * 60;
		long nm = 1000 * 60;
		long ns = 1000;
		// 获得两个时间的毫秒时间差异
		long diff = endDate.getTime() - biginDate.getTime();
		// 计算差多少天
		long day = diff / nd;
		// 计算差多少小时
		long hour = diff % nd / nh;
		// 计算差多少分钟
		long min = diff % nd % nh / nm;
		// 计算差多少秒
		long sec = diff % nd % nh % nm / ns;
		return day == 0L
				? (hour == 0L ? (min == 0 ? (sec + "秒") : min + "分钟" + sec + "秒")
						: hour + "小时" + min + "分钟" + sec + "秒")
				: day + "天" + hour + "小时" + min + "分钟" + sec + "秒";
	}

	/**
	 * 比较日期大小，仅比较年月日
	 * 
	 * @param date1
	 * @param date2
	 * @return 1 data1>date2; 0 data1=date2; -1 data1<date2
	 */
	public static int dateCompare(Date date1, Date date2) {
		String dateFirst = DateFormatUtils.format(date1, DatePattern.YYYYMMDD);
		String dateLast = DateFormatUtils.format(date2, DatePattern.YYYYMMDD);
		int dateFirstIntVal = Integer.parseInt(dateFirst);
		int dateLastIntVal = Integer.parseInt(dateLast);
		return Integer.compare(dateFirstIntVal, dateLastIntVal);
	}

	/**
	 * 获取某个日期的开始时间戳
	 * 
	 * @param d
	 * @return
	 */
	public static long getDayStartTime(Date date) {
		Calendar calendar = Calendar.getInstance();
		if (date != null) {
			calendar.setTime(date);
		}
		calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTimeInMillis();
	}

	/**
	 * 获取某个日期的结束时间戳
	 * 
	 * @param d
	 * @return
	 */
	public static long getDayEndTime(Date date) {
		Calendar calendar = Calendar.getInstance();
		if (date != null) {
			calendar.setTime(date);
		}
		calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
		calendar.set(Calendar.MILLISECOND, 999);
		return calendar.getTimeInMillis();
	}

	/**
	 * 获取当天剩余多少秒，至少间隔1秒，不会为0，若小于1会被修正为1
	 * 
	 * @return
	 */
	public static long getRemainSeconds() {
		LocalDateTime now = LocalDateTime.now();
		LocalDateTime midnight = now.plusDays(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
		long seconds = ChronoUnit.SECONDS.between(now, midnight);
		return seconds <= 0 ? 1 : seconds;
	}
	
	/** 
     * 获取两个日期之间的所有日期 
     * @param beginDate 开始日期 
     * @param endDate 结束日期 
     * @return 
     */ 
    public static List<String> betweenDays(String beginDate, String endDate) {
        // 返回的日期集合 
        List<String> days = new ArrayList<String>(); 
        DateFormat dateFormat = new SimpleDateFormat(DatePattern.YYYY_MM_DD);
        try { 
            Date start = dateFormat.parse(beginDate); 
            Date end = dateFormat.parse(endDate); 
            Calendar tempStart = Calendar.getInstance(); 
            tempStart.setTime(start); 
            Calendar tempEnd = Calendar.getInstance(); 
            tempEnd.setTime(end); 
            tempEnd.add(Calendar.DATE, +1);// 日期加1(包含结束) 
            while (tempStart.before(tempEnd)) { 
                days.add(dateFormat.format(tempStart.getTime()));
                tempStart.add(Calendar.DAY_OF_YEAR, 1); 
            } 
        } catch (ParseException e) { 
            e.printStackTrace(); 
        } 
        return days;
    }
    
    /** 
     * 获取两个日期之间的所有日期 
     * @param beginDate 开始日期 
     * @param endDate 结束日期 
     * @return 
     */ 
    public static List<Date> betweenDays(Date beginDate, Date endDate) {
    	// 返回的日期集合 
    	List<Date> days = new ArrayList<Date>();
    	Calendar tempStart = Calendar.getInstance();
    	tempStart.setTime(beginDate); 
    	Calendar tempEnd = Calendar.getInstance();
    	tempEnd.setTime(endDate); 
    	tempEnd.add(Calendar.DATE, +1);// 日期加1(包含结束) 
    	while (tempStart.before(tempEnd)) { 
    		days.add(tempStart.getTime());
    		tempStart.add(Calendar.DAY_OF_YEAR, 1);
    	} 
    	return days;
    }
	
}
